package timing.ukulele.android.bluetooth.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;

import androidx.core.view.MotionEventCompat;

import timing.ukulele.android.R;

public class PullRefreshListView extends ListView implements OnScrollListener, PullHeadView.OnStateListerer {
    private static final int STATE_NORMAL = 0;
    private static final int STATE_READY = 1;
    private static final int STATE_PULL = 2;
    private static final int STATE_UPDATING = 3;
    private static final int INVALID_POINTER_ID = -1;
    protected PullHeadView mListHeaderView;
    private int mActivePointerId;
    private float mLastY;
    private int mState;
    private int mTouchSlop;
    private Context mContext;
    private PullHeadView mHeadView;
    private int mHeaderHeight = 0;
    protected boolean hasHeader;
    protected boolean hasMoreData = true;
    protected boolean isCanLoadMore = true;
    protected boolean isNeedRetry = false;
    protected boolean isAutoLoading = true;
    protected boolean isBusy = false;
    protected OnRefreshListener mOnRefreshListener;
    protected startListener mListener;
    protected OnClickFootViewListener mFootViewListener;
    protected OnScrollPositionListener mScrollPositionListener;

    public PullRefreshListView(Context context) {
        super(context);
        this.mContext = context;
    }

    public PullRefreshListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
    }

    public PullRefreshListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.mContext = context;
    }

    public void initView() {
        if (hasHeader) {
            mListHeaderView = new PullHeadView(mContext);
            mListHeaderView.setStateListener(this);
            setHeaderDividersEnabled(false);
            setFooterDividersEnabled(false);
            addHeaderView(mListHeaderView, null, false);
            mState = STATE_NORMAL;
            final ViewConfiguration configuration = ViewConfiguration
                    .get(mContext);
            mTouchSlop = configuration.getScaledTouchSlop();
        }

        super.setOnScrollListener(this);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (hasHeader) {
            if (mState == STATE_UPDATING) {
                return super.dispatchTouchEvent(ev);
            }
            final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;
            switch (action) {
                case MotionEvent.ACTION_DOWN:
                    mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
                    mLastY = ev.getY();
                    isFirstViewTop();
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (mActivePointerId == INVALID_POINTER_ID) {
                        break;
                    }

                    if (mState == STATE_NORMAL) {
                        isFirstViewTop();
                    }

                    if (mState == STATE_READY) {
                        final int activePointerId = mActivePointerId;
                        final int activePointerIndex = MotionEventCompat
                                .findPointerIndex(ev, activePointerId);
                        final float y = MotionEventCompat.getY(ev,
                                activePointerIndex);
                        final int deltaY = (int) (y - mLastY);
                        if (deltaY <= 0 || Math.abs(deltaY) < mTouchSlop) {
                            mState = STATE_NORMAL;
                        } else {
                            mLastY = y;
                            mState = STATE_PULL;
                            ev.setAction(MotionEvent.ACTION_CANCEL);
                            super.dispatchTouchEvent(ev);
                        }
                    }

                    if (mState == STATE_PULL) {
                        final int activePointerId = mActivePointerId;
                        final int activePointerIndex = MotionEventCompat
                                .findPointerIndex(ev, activePointerId);
                        final float y = MotionEventCompat.getY(ev,
                                activePointerIndex);
                        final int deltaY = (int) (y - mLastY);
                        mLastY = y;
                        mHeaderHeight += deltaY;
                        setHeaderHeight(mHeaderHeight * 4 / 9);
//					final int headerHeight = mListHeaderView.getHeight();
//					setHeaderHeight(headerHeight + deltaY * 4 / 9);
                        return true;
                    }

                    break;
                case MotionEvent.ACTION_CANCEL:
                case MotionEvent.ACTION_UP:
                    mActivePointerId = INVALID_POINTER_ID;
                    if (mState == STATE_PULL) {
                        update();
                    }
                    break;
                case MotionEventCompat.ACTION_POINTER_DOWN:
                    final int index = MotionEventCompat.getActionIndex(ev);
                    final float y = MotionEventCompat.getY(ev, index);
                    mLastY = y;
                    mActivePointerId = MotionEventCompat.getPointerId(ev, index);
                    break;
                case MotionEventCompat.ACTION_POINTER_UP:
                    onSecondaryPointerUp(ev);
                    break;
            }
        }
        return super.dispatchTouchEvent(ev);
    }

    private void onSecondaryPointerUp(MotionEvent ev) {
        final int pointerIndex = MotionEventCompat.getActionIndex(ev);
        final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
        if (pointerId == mActivePointerId) {
            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
            mLastY = MotionEventCompat.getY(ev, newPointerIndex);
            mActivePointerId = MotionEventCompat.getPointerId(ev,
                    newPointerIndex);
        }
    }

    private void setHeaderHeight(int height) {
        mListHeaderView.setHeaderHeight(height);
    }

    private boolean isFirstViewTop() {
        final int count = getChildCount();
        if (count == 0) {
            return true;
        }
        final int firstVisiblePosition = this.getFirstVisiblePosition();
        final View firstChildView = getChildAt(0);
        boolean needs = firstChildView.getTop() == 0
                && (firstVisiblePosition == 0);
        if (needs) {
            mState = STATE_READY;
        }

        return needs;
    }

    /**
     * 在下拉刷新完成后更换状态
     *
     * @param refreshSuccess 是否获取数据成功
     */
    public void onRefreshComplete(boolean refreshSuccess) {
        if (mListHeaderView != null) {
            if (mState == STATE_UPDATING) {
                mListHeaderView.reset(STATE_NORMAL);
            }
            if (refreshSuccess) {
                mListHeaderView.updateLastTimeLable();
            }
        }
    }

    public void setState(int state) {
        mState = state;
    }

    private void update() {
        if (mListHeaderView.isUpdateNeeded()) {
            mListHeaderView.startUpdate();
            mState = STATE_UPDATING;
            if (mOnRefreshListener != null) {
                mOnRefreshListener.onRefresh();
            }

        } else {
            mListHeaderView.reset(STATE_NORMAL);
        }
    }

    @Override
    public void onReset() {
        mState = STATE_NORMAL;
        mHeaderHeight = 0;
    }

    public boolean canHandleItemClick() {
        return mState == STATE_NORMAL || mState == STATE_READY;
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
                         int visibleItemCount, int totalItemCount) {

        if (mScrollPositionListener != null) {
            mScrollPositionListener.onScroll(view, firstVisibleItem,
                    visibleItemCount, totalItemCount);
        }
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {

        switch (scrollState) {
            case OnScrollListener.SCROLL_STATE_IDLE:
                isBusy = false;
                int first = getFirstVisiblePosition();
                int count = getChildCount();
                int nHeadCount = getHeaderViewsCount();
                int currPosition;
                for (int i = 0; i < count; i++) {
                    currPosition = first - nHeadCount + i;
                    if (currPosition == -nHeadCount) {
                        continue;// 下拉刷新标题栏
                    }
                    if (currPosition >= getCount()) {// 加载更多布局显示的时候
                        return;
                    }
                    if (mListener != null) {
                        mListener.serListViewBusy(currPosition, i);
                    }
                }
                break;
            case OnScrollListener.SCROLL_STATE_FLING:
                isBusy = true;
                break;
            case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
                isBusy = true;
                break;
            default:
                break;
        }

        if (mScrollPositionListener != null) {
            mScrollPositionListener.onScrollStateChanged(view, scrollState);
        }
    }

    public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
        mOnRefreshListener = onRefreshListener;
    }

    public void setOnClickFootViewListener(OnClickFootViewListener listener) {
        mFootViewListener = listener;
    }

    public void setPullTimeTag(String ptg) {
        mListHeaderView.setTimeTag(ptg);
    }

    public boolean isHasMoreData() {
        return hasMoreData;
    }

    public void setHasMoreData(boolean hasMoreData) {
        this.hasMoreData = hasMoreData;
    }

    public boolean isHasHeader() {
        return hasHeader;
    }

    public void setHasHeader(boolean hasHeader) {
        this.hasHeader = hasHeader;
    }

    public boolean isBusy() {
        return this.isBusy;
    }

    public void onRefresh() {
        if (mOnRefreshListener != null) {
            if (hasHeader) {
                mOnRefreshListener.onRefresh();
            }
        }
    }

    public interface OnRefreshListener {
        public void onRefresh();
    }

    public interface OnScrollPositionListener {
        public void onScrollStateChanged(AbsListView view, int scrollState);

        public void onScroll(AbsListView view, int firstVisibleItem,
                             int visibleItemCount, int totalItemCount);
    }

    public interface OnClickFootViewListener {

        public void onClickFootView();
    }

    public interface startListener {
        public void serListViewBusy(int currPosition, int tag);
    }

    public void setSartListener(startListener listener) {
        this.mListener = listener;
    }

    @Override
    public boolean onTrackballEvent(MotionEvent event) {
        return true;
    }

    public boolean isAutoLoading() {
        return isAutoLoading;
    }

    public void startUpdateImmediate() {
        if (mState == STATE_UPDATING) {
            return;
        }
        setSelectionFromTop(0, 0);
        mListHeaderView.moveToUpdateHeight();
        update();
    }

    public OnScrollPositionListener getOnScrollPositionListener() {
        return mScrollPositionListener;
    }

    public void setOnScrollPositionListener(
            OnScrollPositionListener mScrollPositionListener) {
        this.mScrollPositionListener = mScrollPositionListener;
    }

    public void Clear() {
        if (mHeadView != null) {
            removeHeaderView(mHeadView);
        }
        removeAllViewsInLayout();
    }

    public void applyPullRefreshViewTheme() {
        if (mContext != null) {
            this.setBackgroundColor(mContext.getResources().getColor(R.color.timeline_home_bg_color));
        }
        if (mListHeaderView != null) {
            mListHeaderView.applyPullHeadViewTheme();
        }
        if (mHeadView != null) {
            mHeadView.applyPullHeadViewTheme();
        }
    }
}
